#ifndef __POPUP_CLIENT_UI_HPP__
#define __POPUP_CLIENT_UI_HPP__

#include <string>
#include "PopupLibTypes.hpp"

namespace Popup
{
  //============================================================================
  // API which a client UI shall implement
  //============================================================================

  //! This class defines the API which a client user interface
  //! shall implement.
  struct ClientUI
  {
    virtual ~ClientUI() {}
    //!
    //! Event raised to notify client UI when a message comes along with
    //! an attached media file which might take time to be fully received.
    //! When media is completely received, a last event is raised, with
    //! (p_totalSize = p_receivedSize).
    //!
    //! \param[in] p_file         Media file being received
    //! \param[in] p_totalSize    Total size (in bytes) of the media file
    //! \param[in] p_receivedSize Total size (in bytes) already received.
    //!
    virtual void onFileTransferUpdate(const Popup::FileTransfer & p_transfer) = 0;

    //!
    //! Event raised when a message has been received
    //! and is ready to be displayed
    //!
    virtual void onMessageReceived(const UserMessage & p_message) = 0;

    virtual void onMessageSent(const UserMessage & p_message) = 0;

    //!
    //! Event raised when a message reaction has been received
    //!
    virtual void onMessageReactionReceived(const RateUserMessage & p_reaction) = 0;

    //!
    //! Event raised when a message reaction has been received
    //!
    virtual void onOpinionRequested(const Canvass & p_canvass) = 0;

    //!
    //! A vote had been submitted by a user
    //!
    virtual void onVoteReceived(const Vote & p_vote) = 0;

    //!
    //! An invitation to an existing thread has been received
    virtual void onInvitationReceived(const ThreadInvitation & p_invitation) = 0;

    //!
    //! Event raised when connection status changed (up or down).
    //!
    //! \param[in] p_myself     PopupUser Tells if client if connected or not
    //!
    virtual void onConnectionUpdate(bool p_connected,
                                    const User & p_myself = NullUser,
                                    SessionID p_sessionID = 0) = 0;

    //!
    //! Event raised when a user info has been updated
    //! (including user disconnection)
    //!
    //! \param[in] p_user       Profile of the user which has been updated
    //! \param[in] p_updateMask Bit field telling which fields have been updated
    //! \param[in] p_isNewUser  Tells if this user has just connected
    //!
    virtual void onUserUpdate(const User & p_user,
                              unsigned short p_updateMask,
                              bool p_isNewUser) = 0;

    //!
    //! Event raise when statistics are updated
    //!
    virtual void onUserStatisticsUpdate(UserID p_userID,
                                        UserStatistics & p_stats) = 0;

    //!
    //! \return The temporary directory which must be used in order
    //! to save the media files which are sent by client's friends.
    //!
    virtual std::string getTemporaryDir() = 0;

    //!
    //! \return The resource directory where user private file are stored
    //!
    virtual std::string getResourceDir() = 0;
  };

  //============================================================================
  // API of a Popup client
  //============================================================================

  struct Client
  {
    virtual ~Client() {}

    //! Connects to the specified server, using specified login and password
    virtual ConnectionEcode connect(const std::string & p_server,
                                    unsigned short p_port,
                                    const std::string & p_login,
                                    const std::string & p_password,
                                    bool p_register = false) = 0;

    //! Disconnects from the client
    virtual bool disconnect() = 0;

    //! Send the specified message over the network
    //! \return True upon successful completion
    //! 
    virtual bool sendMessage(UserMessage & p_message) = 0;

    //! Send the specified message over the network
    //! \return True upon successful completion
    //!
    virtual bool sendMessageReaction(const RateUserMessage & p_message) = 0;

    //! Send vote of the user
    virtual bool sendVote(const Vote & p_vote) = 0;

    //! Submits a new opinion request
    //! \return True upon successful completion
    //!
    virtual bool submitCanvass(Canvass & p_canvass) = 0;

    //! Tells server that we've modified our profile
    virtual bool notifyUserUpdate(const User *p_myself,
                                  unsigned short p_updateMask) = 0;

    //! Sends an invitation to join an existing thread
    virtual bool sendInvitation(const ThreadInvitation & p_invitation) = 0;

    //! Connects to the server with specific connection parameters, and
    //! receives user's profile sent by server
    //! \return A brand new client instance if connection to server succeeds,
    //!         0 otherwise.
    static Client *newClient(ClientUI *p_clientUI);
  };
}

#endif // __POPUP_CLIENT_UI_HPP__
